/*
 * Copyright 2006 Matt Jensen
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
 * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations under the License.
 */
package org.spectaql.internal.query;

import org.spectaql.internal.SpectaqlContextInternal;
import org.spectaql.internal.proxy.ProxyInternal;
import org.spectaql.metadata.PropertyMetadata;

/**
 * <p>
 * <code>AbstractEntityProxy</code> is ...
 * </p>
 */
public abstract class AbstractEntityProxy implements ProxyInternal
{
    /**
     * <p>
     * The query context.
     * </p>
     */
    private final QueryContextInternal m_queryContext;

    
    /**
     * <p>
     * Construct a {@link AbstractEntityProxy} instance.
     * </p>
     *
     * @param queryContext the query context.
     */
    public AbstractEntityProxy(final QueryContextInternal queryContext)
    {
        super();
        assert null != queryContext : "The [queryContext] argument cannot be null.";

        m_queryContext = queryContext;
    }

    /* inherit javadoc */
    public Object handlePropertyRead(final PropertyMetadata propertyMetadata)
    {
        // Store information on the property read; different subclasses will handle this differently.
        storePropertyRead(m_queryContext, propertyMetadata);

        // Return the appropriate type of object depending upon the property class.
        final Object result;
        final Class<?> propertyClass = propertyMetadata.getPropertyClass();
        final SpectaqlContextInternal spectaqlContext = m_queryContext.getSpectaqlContext();
        if (!spectaqlContext.isEntityClass(propertyClass))
        {
            result = null;
        }
        else
        {
            result = spectaqlContext.createProxy(propertyClass, new PropertyReferenceCapturingProxy(m_queryContext));
        }
        return result;
    }

    /* inherit javadoc */
    public void handlePropertyWrite(final PropertyMetadata propertyMetadata, final Object value)
    {
        // TODO: handle setter invocations?
        throw new UnsupportedOperationException();
    }

    /**
     * <p>
     * Store information on a property read into the query context as appropriate for the particular proxy type.
     * </p>
     *
     * @param queryContext the query context.
     * @param propertyMetadata the metadata for the property which was accessed.
     */
    protected abstract void storePropertyRead(QueryContextInternal queryContext, PropertyMetadata propertyMetadata);
}
